package com.jeehentor.system.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jeehentor.common.api.vo.LoginUser;
import com.jeehentor.common.exception.HentorException;
import com.jeehentor.common.vo.Result;
import com.jeehentor.dto.IdsRequestDTO;
import com.jeehentor.dto.QuerySysUserDTO;
import com.jeehentor.entity.*;
import com.jeehentor.system.mapper.SysDepartMapper;
import com.jeehentor.system.mapper.SysRoleMapper;
import com.jeehentor.system.mapper.SysUserMapper;
import com.jeehentor.system.mapper.SysUserRoleMapper;
import com.jeehentor.system.service.ISysLogService;
import com.jeehentor.system.service.ISysUserService;
import com.jeehentor.utils.ClientIPUtil;
import com.jeehentor.utils.JWTUtil;
import com.jeehentor.utils.RedisUtils;
import com.jeehentor.utils.SecurityUtil;
import com.jeehentor.vo.UserVO;
import jakarta.servlet.http.HttpServletRequest;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

import static com.jeehentor.common.constant.CacheConstants.LOGIN_USER;


/**
 * <p>
 * 用户表 服务实现类
 * </p>
 *
 * @author wzd
 * @since 2024-04-08
 */
@Service
@RequiredArgsConstructor
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements ISysUserService {

    private final AuthenticationManagerBuilder authenticationManagerBuilder;

    private final RedisUtils redisUtils;

    private final PasswordEncoder passwordEncoder;

    private final SysUserMapper sysUserMapper;

    private final SysDepartMapper departMapper;

    private final SysUserRoleMapper userRoleMapper;

    private final SysRoleMapper sysRoleMapper;

    private final ISysLogService sysLogService;
    @Override
    public Result<String> login(LoginUser user,HttpServletRequest request) {
        Authentication authentication;
        //用户认证
        try {
            UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword());
            authentication = authenticationManagerBuilder.getObject().authenticate(usernamePasswordAuthenticationToken);
        }catch (BadCredentialsException e){
            //密码错误5次，锁定5分钟
            Object o = redisUtils.getValueOperations().get(user.getUsername() + "_login_count");
            if(o != null){
                String s = o.toString();
                int count = Integer.parseInt(s);
                if(count >= 5){
                    throw new HentorException("密码错误次数过多，请稍后再试");
                }
                redisUtils.getValueOperations().set(user.getUsername()+"_login_count", String.valueOf(count+1), 5, TimeUnit.MINUTES);
            }else{
                redisUtils.getValueOperations().set(user.getUsername()+"_login_count", "1", 5, TimeUnit.MINUTES);
            }
            throw new HentorException("用户名或密码错误");
        }
        LoginUser userDetails = (LoginUser) authentication.getPrincipal();
        //生成jwt并返回
        String token = JWTUtil.createToken(userDetails);
        redisUtils.getValueOperations().set(LOGIN_USER+user.getUsername(), JSON.toJSONString(userDetails), 7, TimeUnit.DAYS);
        saveLoginLog(userDetails,userDetails.getUsername()+"登录成功！","login",request);
        return Result.OK(token);
    }

    @Override
    public void logout(HttpServletRequest request) {
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        saveLoginLog(loginUser,loginUser.getUsername()+"退出登录！","logout",request);
        redisUtils.getValueOperations().getOperations().delete(loginUser.getUsername());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void register(LoginUser user) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(user, sysUser);
        SysUser one = getOne(new QueryWrapper<>(new SysUser().setUsername(user.getUsername())));
        if(one != null){
            throw new HentorException("该用户名已被注册");
        }
        if(StringUtils.isBlank(user.getPassword())){
            user.setPassword("123456");
        }
        sysUser.setPassword(passwordEncoder.encode(user.getPassword()));
        if(StringUtils.isBlank(user.getRealname())){
            sysUser.setRealname(user.getUsername());
        }
        LoginUser loginUser = (LoginUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
        if(loginUser != null){
            sysUser.setCreateBy(loginUser.getId());
        }
        save(sysUser);
        //角色
        LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysRoleLambdaQueryWrapper.in(SysRole::getRoleCode,user.getRoles());
        sysRoleLambdaQueryWrapper.eq(SysRole::getStatus,'1');
        List<SysRole> sysRoles = sysRoleMapper.selectList(sysRoleLambdaQueryWrapper);
        if(CollectionUtil.isNotEmpty(sysRoles)){
            sysRoles.forEach(x->{
                SysUserRole sysUserRole = new SysUserRole();
                sysUserRole.setUserId(sysUser.getId());
                sysUserRole.setRoleId(x.getId());
                userRoleMapper.insert(sysUserRole);
            });
        }
    }

    @Override
    public void updatePwd(LoginUser user) {
        if (user == null || StringUtils.isBlank(user.getId())) {
            throw new HentorException("用户ID不能为空");
        }
        if (StringUtils.isBlank(user.getOriginalPwd())) {
            throw new HentorException("原密码不能为空");
        }
        if (StringUtils.isBlank(user.getPassword())) {
            throw new HentorException("新密码不能为空");
        }

        // 查询数据库中当前用户
        SysUser sysUser = getById(user.getId());
        if (sysUser == null) {
            throw new HentorException("用户不存在");
        }

        // 校验原密码是否正确（注意：数据库里是加密后的，要用 matches 方法对比）
        if (!passwordEncoder.matches(user.getOriginalPwd(), sysUser.getPassword())) {
            throw new HentorException("原密码错误");
        }

        // 更新新密码
        sysUser.setPassword(passwordEncoder.encode(user.getPassword()));
        sysUser.setUpdateTime(LocalDateTime.now());
        sysUser.setUpdateBy(SecurityUtil.getCurrentUser().getId());

        updateById(sysUser);

        // 删除Redis缓存，强制用户重新登录
        redisUtils.common.delete(LOGIN_USER + sysUser.getUsername());
    }

    @Override
    public LoginUser findUserByName(String username) {
        //根据username查询用户信息
        SysUser sysUser = getOne(new QueryWrapper<SysUser>().lambda().eq(SysUser::getUsername, username));
        LoginUser loginUser = new LoginUser();
        if(sysUser != null){
            BeanUtils.copyProperties(sysUser,loginUser);
        }
        return loginUser;
    }


    @Override
    public List<String> getPermissionList(String userId) {
        ArrayList<String> strings = new ArrayList<>();
        List<String> permissionList = sysUserMapper.getPermissionList(userId);
        for (String permission:permissionList) {
            strings.addAll(Arrays.asList(permission.trim().split(",")));
        }
        return strings;
    }

    @Override
    public List<String> getRoleList(String userId) {
        return sysUserMapper.getRoleList(userId);
    }

    @Override
    public Page<UserVO> pageList(QuerySysUserDTO user) {
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserLambdaQueryWrapper.eq(StringUtils.isNotBlank(user.getOrgCode()),SysUser::getOrgCode, user.getOrgCode());
        sysUserLambdaQueryWrapper.like(StringUtils.isNotBlank(user.getUsername()),SysUser::getUsername, user.getUsername());
        sysUserLambdaQueryWrapper.like(StringUtils.isNotBlank(user.getRealname()),SysUser::getRealname, user.getRealname());
        Page<SysUser> page = page(user.getPage(), sysUserLambdaQueryWrapper);
        Page<UserVO> userVOPage = new Page<>();
        // 设置分页总记录数
        userVOPage.setTotal(page.getTotal());
        // 设置分页显示记录数
        userVOPage.setSize(page.getSize());
        // 设置分页当前页码
        userVOPage.setCurrent(page.getCurrent());
        // 设置分页总页码
        userVOPage.setPages(page.getPages());
        List<UserVO> collect = page.getRecords().stream().map(x -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(x, userVO);
            //查询角色
            List<String> roleList = getRoleList(x.getId());
            userVO.setRoles(roleList);
            //查询部门名称
            LambdaQueryWrapper<SysDepart> sysDepartLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysDepartLambdaQueryWrapper.eq(SysDepart::getOrgCode,x.getOrgCode());
            SysDepart sysDepart = departMapper.selectOne(sysDepartLambdaQueryWrapper);
            if(sysDepart != null){
                userVO.setDepartName(sysDepart.getDepartName());
            }
            return userVO;
        }).collect(Collectors.toList());
        userVOPage.setRecords(collect);
        return userVOPage;
    }

    @Override
    public void updateUser(LoginUser user) {
        SysUser one = getOne(new QueryWrapper<>(new SysUser().setUsername(user.getUsername())));
        if(one != null && !user.getId().equals(one.getId())){
            throw new HentorException("该用户名已被注册");
        }
        UpdateWrapper<SysUser> sysUserUpdateWrapper = new UpdateWrapper<>();
        sysUserUpdateWrapper.eq("id",user.getId());
        sysUserUpdateWrapper.set("realname",user.getRealname());
        sysUserUpdateWrapper.set("email",user.getEmail());
        sysUserUpdateWrapper.set("phone",user.getPhone());
        sysUserUpdateWrapper.set("sex",user.getSex());
        sysUserUpdateWrapper.set("avatar",user.getAvatar());
        sysUserUpdateWrapper.set("update_time",new Date());
        sysUserUpdateWrapper.set("update_by", SecurityUtil.getCurrentUser().getId());
        sysUserUpdateWrapper.set("org_code",user.getOrgCode());
        sysUserUpdateWrapper.set("status",user.getStatus());
        update(new SysUser().setId(user.getId()),sysUserUpdateWrapper);
        if(CollectionUtil.isNotEmpty(user.getRoles())){
            //删除角色信息
            userRoleMapper.delete(new QueryWrapper<>(new SysUserRole().setUserId(user.getId())));
            //添加角色信息
            LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysRoleLambdaQueryWrapper.in(SysRole::getRoleCode,user.getRoles());
            sysRoleLambdaQueryWrapper.eq(SysRole::getStatus,'1');
            List<SysRole> sysRoles = sysRoleMapper.selectList(sysRoleLambdaQueryWrapper);
            if(CollectionUtil.isNotEmpty(sysRoles)){
                sysRoles.forEach(x->{
                    SysUserRole sysUserRole = new SysUserRole();
                    sysUserRole.setUserId(user.getId());
                    sysUserRole.setRoleId(x.getId());
                    userRoleMapper.insert(sysUserRole);
                });
            }
        }
        //清除用户缓存
        redisUtils.common.delete(LOGIN_USER+user.getUsername());
    }

    @Override
    public void delUser(IdsRequestDTO ids) {
        //删除角色信息
        LambdaQueryWrapper<SysUserRole> sysUserRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysUserRoleLambdaQueryWrapper.in(SysUserRole::getUserId,ids.getIds());
        userRoleMapper.delete(sysUserRoleLambdaQueryWrapper);
        //删除用户信息
        sysUserMapper.deleteBatchIds(ids.getIds());
    }

    @Override
    public void restPwd(LoginUser user) {
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(user,sysUser);
        if(StringUtils.isBlank(user.getPassword())){
            user.setPassword("123456");
        }
        sysUser.setPassword(passwordEncoder.encode(user.getPassword()));
        updateById(sysUser);
    }

    @Override
    public Page<UserVO> pageListByOrg(QuerySysUserDTO user) {
        LambdaQueryWrapper<SysUser> sysUserLambdaQueryWrapper = new LambdaQueryWrapper<>();
        if(StringUtils.isNotBlank(user.getOrgCode())){
            LambdaQueryWrapper<SysDepart> departLambdaQueryWrapper = new LambdaQueryWrapper<>();
            departLambdaQueryWrapper.eq(SysDepart::getOrgCode,user.getOrgCode());
            SysDepart depart = departMapper.selectOne(departLambdaQueryWrapper);
            ArrayList<String> orgCodeList = new ArrayList<>();
            orgCodeList.add(depart.getOrgCode());
            getDepartChildList(depart,orgCodeList);
            sysUserLambdaQueryWrapper.in(StringUtils.isNotBlank(user.getOrgCode()),SysUser::getOrgCode, orgCodeList);
        }
        sysUserLambdaQueryWrapper.like(StringUtils.isNotBlank(user.getUsername()),SysUser::getUsername, user.getUsername());
        sysUserLambdaQueryWrapper.like(StringUtils.isNotBlank(user.getRealname()),SysUser::getRealname, user.getRealname());
        Page<SysUser> page = page(user.getPage(), sysUserLambdaQueryWrapper);
        Page<UserVO> userVOPage = new Page<>();
        // 设置分页总记录数
        userVOPage.setTotal(page.getTotal());
        // 设置分页显示记录数
        userVOPage.setSize(page.getSize());
        // 设置分页当前页码
        userVOPage.setCurrent(page.getCurrent());
        // 设置分页总页码
        userVOPage.setPages(page.getPages());
        List<UserVO> collect = page.getRecords().stream().map(x -> {
            UserVO userVO = new UserVO();
            BeanUtils.copyProperties(x, userVO);
            //查询角色
            List<String> roleList = getRoleList(x.getId());
            userVO.setRoles(roleList);
            //查询部门名称
            LambdaQueryWrapper<SysDepart> sysDepartLambdaQueryWrapper = new LambdaQueryWrapper<>();
            sysDepartLambdaQueryWrapper.eq(SysDepart::getOrgCode,x.getOrgCode());
            SysDepart sysDepart = departMapper.selectOne(sysDepartLambdaQueryWrapper);
            if(sysDepart != null){
                userVO.setDepartName(sysDepart.getDepartName());
            }
            return userVO;
        }).collect(Collectors.toList());
        userVOPage.setRecords(collect);
        return userVOPage;
    }

    private List<String> getDepartChildList(SysDepart depart,List<String> departChildList){
        LambdaQueryWrapper<SysDepart> sysDepartLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysDepartLambdaQueryWrapper.eq(SysDepart::getParentId,depart.getId());
        List<SysDepart> sysDeparts = departMapper.selectList(sysDepartLambdaQueryWrapper);
        if(CollectionUtil.isNotEmpty(sysDeparts)){
            sysDeparts.forEach(x->{
                departChildList.add(x.getOrgCode());
                getDepartChildList(x,departChildList);
            });
        }
        return departChildList;
    }


    /**
     * 登录日志
     * @param user
     * @param msg
     */
    private void saveLoginLog(LoginUser user, String msg, String opt, HttpServletRequest request){
        SysLog sysLog = new SysLog();
        sysLog.setUserid(user.getId());
        sysLog.setUsername(user.getUsername());
        sysLog.setLogContent(msg);
        sysLog.setLogType(1);
        sysLog.setOperateType(opt);
        sysLog.setIp(ClientIPUtil.getClientIP(request));
        sysLog.setCreateBy(user.getId());
        sysLogService.save(sysLog);
    }

    @Override
    public String getRoleByCode(String code){
        LambdaQueryWrapper<SysRole> sysRoleLambdaQueryWrapper = new LambdaQueryWrapper<>();
        sysRoleLambdaQueryWrapper.eq(SysRole::getRoleCode,code);
        return sysRoleMapper.selectOne(sysRoleLambdaQueryWrapper).getRoleName();
    }

    @Override
    public void updateUserInfo(LoginUser user) {
        if (user == null || StringUtils.isBlank(user.getId())) {
            throw new HentorException("用户ID不能为空");
        }
        // 查询数据库中当前用户
        SysUser sysUser = getById(user.getId());
        if (sysUser == null) {
            throw new HentorException("用户不存在");
        }
        sysUser.setEmail(user.getEmail());
        sysUser.setPhone(user.getPhone());
        sysUser.setRealname(user.getRealname());
        updateById(sysUser);
    }
}
